package com.zombies.list.linkedlist.doublelinkedlist;

import com.sun.deploy.ref.Helpers;
import com.sun.scenario.effect.impl.HeapImage;
import com.zombies.list.adt.MyList;

/**
 * 头指针，头结点（人为设置）和首元结点（第一个元素结点）还有尾结点
 *
 * 约定：头指针指向首元结点
 *
 * @author zombies
 * @create 2022-04-22 10:42
 */
public class MyDoubleLikedList<E> implements MyList<E> {


    //头指针
    Node<E> first;

    //尾指针
    Node<E> last;

    public MyDoubleLikedList() {
    }
    public MyDoubleLikedList(E e) {
        this();
        addLast(e);
    }

    /**
     * 定义一个双向链表结点
     * @param <E>
     */
    private static class Node<E>{
        E data;
        Node<E> prev;
        Node<E> next;

        public Node(Node<E> pre,E data,  Node<E> next) {
            this.prev = pre;
            this.data = data;
            this.next = next;
        }

    }

    @Override
    public boolean isEmpty() {
        return first.next == null;
    }

    @Override
    public boolean isFull() {
        return false;
    }

    @Override
    public E getFirst() {
        return first.data;
    }

    @Override
    public E getLast() {
        return last.data;
    }

    @Override
    public E removeFirst() {
        Node<E> temp = first;
        E e = temp.data;
        if(temp != null){
            //要断开前后联系
            first = temp.next; //first后移
            first.prev = null; //first前指针置空
            temp.next = null;
        }
        return e;
    }

    @Override
    public E removeLast() {
        Node<E> temp = last;
        E e = temp.data;
        if(temp.prev != null){
            last = temp.prev;
            last.next = null;
            temp.prev = null;
        }
        return e;
    }

    @Override
    public void addFirst(E e) {
        Node<E> temp = first;
        Node<E> newNode = new Node<E>(null,e,temp);
        first = newNode;
        if(temp == null){
            last = newNode;
        }else {
            temp.prev = newNode;
        }

    }

    @Override
    public void addLast(E e) {
        Node<E> temp = last;
        Node<E> newNode = new Node<E>(temp, e, null);
        last = newNode;
        if(temp == null){
            first = newNode;
        }else {
            temp.next = newNode;
        }
    }

    @Override
    public boolean contains(E e) {
        Node<E> temp = first;
        while (temp != null) {
            if(e != null && e.equals(temp.data)){
                return true;
            }
            temp = temp.next;
        }
        return false;
    }

    @Override
    public int size() {
        Node<E> temp = first;
        int len = 0;
        while(temp != null){
            temp = temp.next;
            len++;
        }
        return len;
    }

    /**
     * 体验了一把值传递的应用
     *
     * @param e 将要插入的目标元素
     * @return
     */
    @Override
    public boolean add(E e) {
        Node<E> temp = last;
        Node<E> newNode = new Node<E>(temp,e,null);
        last = newNode;

        //考虑结点为空的时候
        if(temp == null){
            first = newNode; //对first结点管理
        }else {
            temp.next = newNode;
        }
        return true;
    }

    /**
     * 这个用法是照搬LinkedList里面的remove方法的思路
     *
     * @param e 将要删除的目标元素
     * @return
     */
    @Override
    public boolean remove(E e) {
        Node<E> temp = first;

        if(temp == null){
            return false;
        }

        while (temp != null) {
            if(e != null && e.equals(temp.data)){
                break;
            }
            temp = temp.next;
        }

        Node<E> prev = temp.prev;
//        E element = temp.data;
        Node<E> next = temp.next;

        //处理目标结点与前结点的关系
        if(prev == null){
            first = next;
        }else {
            prev.next = next;
            temp.prev = null; //断开目标结点prev指针
        }

        //处理目标结点与后结点的关系
        if(next == null){
            last = prev;
        }else {
            next.prev = prev;
            temp.next = null;//断开目标结点next指针
        }

        return true;
    }

    /**
     * 传入双向链表
     * @param list 将要添加的目标元素集合
     * @return
     */
    @Override
    public boolean addAll(MyList<E> list) {

        MyDoubleLikedList doubleLikedList = (MyDoubleLikedList) list;
        if(doubleLikedList == null){
            return false;
        }
        if(first == null){
            first = doubleLikedList.first;
        }else {
            last.next = doubleLikedList.first;
            doubleLikedList.first.prev = last;  //一开始丢了这个前指针 断链了
            last = doubleLikedList.last;
        }
        return true;
    }

    @Override
    public boolean addAll(int index, MyList<E> list) {
        return false;
    }

    @Override
    public void clear() {
        for(Node<E> x = first;x != null;){
            Node<E> next = x.next;
            x.prev = null;
            x.data = null;
            x.next = null;
            x = next;
        }

        first = last = null;
    }

    @Override
    public E get(int index) {
        return null;
    }

    @Override
    public E set(int index, E e) {
        return null;
    }

    @Override
    public void add(int index, E e) {

    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public int indexOf(E e) {
        return 0;
    }

    @Override
    public int lastIndexOf(E e) {
        return 0;
    }

    @Override
    public MyList<E> getReverseList() {
        /*
        有点搞笑，一开始以为直接换了头尾指针就是反转了,这个想法是错误的。
        MyDoubleLikedList<E> newList = new MyDoubleLikedList<>();
        newList.first = this.last;
        newList.last = this.first;
        return newList;*/

        MyDoubleLikedList<E> newList = new MyDoubleLikedList<>();
        Node<E> temp = last;

        while (temp != null){
            newList.add(temp.data); //这里已经处理了last结点
            temp = temp.prev;
        }

        return newList;
    }

    @Override
    public void show() {
        Node<E> temp = first;

        while (temp != null){
            System.out.printf("-"+ temp.data + "-");
            temp = temp.next;
        }
        System.out.println();
    }

    public void showReserver(){
        Node<E> temp = last;

        while (temp != null){
            System.out.printf("-"+ temp.data + "-");
            temp = temp.prev;
        }
        System.out.println();
    }

}
